//
//  Semaphore.m
//  GCDDemo
//
//  Created by everyu on 2018/5/22.
//  Copyright © 2018年 everyu. All rights reserved.
//clear

#import "Semaphore.h"
#import "SafeArray.h"

@interface Semaphore ()

@property (nonatomic, strong) NSMutableArray *array;
@end

@implementation Semaphore

+ (void)entrance
{
    NSLog(@"entrance");
    
    [self fun7];
}

+ (void)fun0
{
    //信号量初始值需 >= 0
    dispatch_semaphore_t sema = dispatch_semaphore_create(-1);
    NSLog(@"%@",sema); //(null)
}

+ (void)fun1
{
    //信号量销毁时信号值不能低于初始值
    dispatch_semaphore_t sema = dispatch_semaphore_create(5);
    dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER);
    //crash
}

+ (void)fun2
{
    NSLog(@"1");
    dispatch_queue_t queue = dispatch_queue_create("com.queue", DISPATCH_QUEUE_CONCURRENT);
    dispatch_async(queue, ^{
        NSLog(@"2");
    });
    NSLog(@"3");
    
    //log: 1 3 2
}

+ (void)fun3
{
    dispatch_semaphore_t sema = dispatch_semaphore_create(0);
    
    NSLog(@"1");
    dispatch_queue_t queue = dispatch_queue_create("com.queue", DISPATCH_QUEUE_CONCURRENT);
    dispatch_async(queue, ^{
        NSLog(@"2");
        
        dispatch_semaphore_signal(sema);
    });
    //会阻塞当前线程，等待唤醒
    dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER);
    NSLog(@"3");
    
    //log: 1 2 3
}

//同步请求
+ (NSData *)fun6
{
    __block NSData *data = nil;
    
    dispatch_semaphore_t sema = dispatch_semaphore_create(0);
    [self featchDataCompletion:^(NSData *result) {
        
        data = result;
        dispatch_semaphore_signal(sema);
    }];
    dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER);
    return data;
}

+ (void)fun4
{
    dispatch_semaphore_t sema = dispatch_semaphore_create(0);

    NSLog(@"beign");
    //超时时间 5s
    dispatch_time_t time = dispatch_time(DISPATCH_TIME_NOW, NSEC_PER_SEC * 5);
    long count = dispatch_semaphore_wait(sema, time);
    if (count == 0) {
        //被唤醒
        
    }else{
        //超时
        NSLog(@"%ld",count); //5s后打印 49,超时返回非0
    }
}

+ (void)fun5
{
    dispatch_semaphore_t sema = dispatch_semaphore_create(0);
    
    NSThread *thread0 = [[NSThread alloc] initWithBlock:^{
        dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER);
        NSLog(@"highPriorityTask");
    }];
    thread0.threadPriority = 0.9;
    
    NSThread *thread1 = [[NSThread alloc] initWithBlock:^{
        dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER);
        NSLog(@"defaultPriorityTask");
    }];
    thread1.threadPriority = 0.5;
    
    NSThread *thread2 = [[NSThread alloc] initWithBlock:^{
        dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER);
        NSLog(@"lowPriorityTask");
    }];
    thread2.threadPriority = 0.2;
    
    [thread2 start];
    [thread1 start];
    [thread0 start];
    
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, NSEC_PER_SEC * 2), dispatch_get_main_queue(), ^{
        NSInteger v = dispatch_semaphore_signal(sema); //优先唤醒优先级高的线程thread0
        if (v == 0) {
            
        }else{
            NSLog(@"唤醒了某个阻塞的线程");
        }
    });
}


+ (void)fun7
{
    //限制并发数
    NSLog(@"begin");
    dispatch_semaphore_t sema = dispatch_semaphore_create(5);
    dispatch_async(dispatch_get_global_queue(0, 0), ^{
        for (int i = 0; i < 100; i ++) {
            dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER);
            dispatch_async(dispatch_get_global_queue(0, 0), ^{
                
                NSData *data = [self fun6];
                NSLog(@"task %d successed %@",i,data);
                
                dispatch_semaphore_signal(sema);
            });
        }
    });
}

+ (void)fun8
{
    
}

#pragma mark - 模拟逻辑代码
//模拟异步请求
+ (void)featchDataCompletion:(void(^)(NSData *result))callback
{
    dispatch_async(dispatch_get_global_queue(0, 0), ^{
        sleep(2);
        if (callback) {
            callback([NSData data]);
        }
    });
}

@end
